/**
 * 
 */
package pers.xwx.titan.filter;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map.Entry;

import com.alibaba.druid.filter.FilterEventAdapter;
import com.alibaba.druid.proxy.jdbc.StatementProxy;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;
import com.alibaba.druid.stat.TableStat;
import com.alibaba.druid.stat.TableStat.Condition;
import com.alibaba.druid.util.JdbcConstants;

import pers.xwx.titan.bo.DruidLogBO;

/**
 * @author user
 *
 */
public class DruidLogFilter extends FilterEventAdapter {

	/**
	 * 数据库类型
	 */
	private String dbType;

	public DruidLogFilter(String dbType) {
		this.dbType = dbType;
	}

	@Override
	protected void statementExecuteBefore(StatementProxy statement, String sql) {
		// 构建对象
		DruidLogBO logObj = new DruidLogBO();
		// 美化SQL
		String sqlBeauty = SQLUtils.format(sql, this.dbType);
		// 保存SQL到对象
		logObj.setOriginalSQL(sqlBeauty);
		// 默认设置Select操作
		logObj.setOperationType(DruidLogBO.Operator.SELECT);
		// 设置操作开始时间
		logObj.setOperatedAt(new Date());
		// 解析SQL
		List<SQLStatement> stmtList = SQLUtils.parseStatements(sqlBeauty, this.dbType);
		for (int i = 0; i < stmtList.size(); i++) {
			SQLStatement stmt = stmtList.get(i);
			// 只查询表名
			List<String> selectTableNames = new ArrayList<>();
			// 解析对象
			switch (this.dbType) {
				case JdbcConstants.MYSQL:
					MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();
					stmt.accept(visitor);
					// 判断是否有非Select操作，目前只操作单一表delete,update,insert操作
					for (Entry<TableStat.Name, TableStat> tableEntry : visitor.getTables().entrySet()) {
						if (tableEntry.getValue().getUpdateCount() > 0) {
							// 更新操作
							logObj.setOperationType(DruidLogBO.Operator.UPDATE);
							logObj.setTable(tableEntry.getKey().getName());
						}
						if (tableEntry.getValue().getDeleteCount() > 0) {
							// 删除操作
							logObj.setOperationType(DruidLogBO.Operator.DELETE);
							logObj.setTable(tableEntry.getKey().getName());
						}
						if (tableEntry.getValue().getInsertCount() > 0) {
							// 插入操作
							logObj.setOperationType(DruidLogBO.Operator.INSERT);
							logObj.setTable(tableEntry.getKey().getName());
						}
						if (tableEntry.getValue().getSelectCount() > 0) {
							// 查询操作
							selectTableNames.add(tableEntry.getKey().getName());
						}
					}
					break;
				default:
					break;
			}
			// TODO
		}
	}

	@Override
	protected void statementExecuteAfter(StatementProxy statement, String sql, boolean result) {
		// 解析SQL，判断类型
		System.err.print("statement id: " + statement.getId());
		// 美化sql
		String sqlBeauty = SQLUtils.format(sql, this.dbType);

		List<SQLStatement> stmtList = SQLUtils.parseStatements(sqlBeauty, this.dbType);

		for (int i = 0; i < stmtList.size(); i++) {

			SQLStatement stmt = stmtList.get(i);
			MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();
			stmt.accept(visitor);

			// 获取操作方法名称,依赖于表名称
			System.out.println("all tables : " + visitor.getTables());
			// 获取字段名称
			System.out.println("all fields : " + visitor.getColumns());
			// 获取字段名称
			for (Condition condition : visitor.getConditions()) {
				System.out.println("condition fields : " + condition.getColumn());
			}
		}

		for (int i = 0; i < statement.getParametersSize(); i++) {
			System.out.println("all parameters : " + statement.getParameter(i).getValue());
		}
		System.out.println(statement.getLastExecuteTimeNano());
		// 执行查询sql，用于批量修改补偿
		try {
			ResultSet queryResults = statement.executeQuery("select id from account where sex = 'male'");
			while (queryResults.next()) {
				String id = queryResults.getString("id");
				System.out.println("query id : " + id);
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		super.statementExecuteAfter(statement, sql, result);
	}

}
